# -- coding: utf-8 --
import sys
import io
from dotenv import load_dotenv

# 设置标准输出的编码为UTF-8
if sys.stdout.encoding != "UTF-8":
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")

import os
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import (
    RecursiveCharacterTextSplitter,
    CharacterTextSplitter,
    TokenTextSplitter,
)

# from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS


load_dotenv()


def create_sample_documents():
    """创建实例文档用于分割演示"""
    print(f"\n📁 创建示例文档")
    print("-" * 40)
    os.makedirs("documents", exist_ok=True)

    # 创建包含多个主题的长文档
    sample_content = """人工智能技术全面解析

第一章：机器学习基础

1.1 什么是机器学习
机器学习是人工智能的一个核心领域，它使计算机系统能够从数据中学习和改进，而无需进行明确的编程。机器学习算法通过分析大量数据来识别模式并做出预测或决策。

1.2 主要机器学习类型
监督学习：使用标记数据训练模型，用于分类和回归任务。常见的算法包括线性回归、逻辑回归、支持向量机和决策树。

无监督学习：在未标记数据中发现隐藏模式，用于聚类和关联分析。常见算法包括K均值聚类、主成分分析和关联规则学习。

强化学习：智能体通过与环境互动学习最优行为策略，通过试错获得奖励最大化。代表性算法包括Q学习和深度强化学习。

第二章：深度学习进阶

2.1 神经网络基础
神经网络受人脑结构启发，由相互连接的神经元组成。前馈神经网络是最基本的类型，信息单向流动从输入层到输出层。

2.2 卷积神经网络(CNN)
CNN专门用于处理网格状数据，如图像。它通过卷积层、池化层和全连接层自动提取图像特征，在计算机视觉领域取得突破性成果。

2.3 循环神经网络(RNN)
RNN适合处理序列数据，具有记忆功能。LSTM和GRU是RNN的变体，解决了长序列训练中的梯度消失问题，广泛应用于自然语言处理和时间序列预测。

第三章：大语言模型与应用

3.1 Transformer架构
Transformer是当前大语言模型的基础架构，采用自注意力机制并行处理序列数据，大幅提高了训练效率和模型性能。

3.2 预训练与微调
大语言模型通常先在大规模语料上进行预训练，学习通用语言表示，然后在特定任务上进行微调，适应具体应用场景。

3.3 RAG技术详解
检索增强生成(RAG)结合了信息检索和文本生成，通过从外部知识库检索相关信息来增强LLM的回答准确性和事实性，有效减少幻觉问题。

第四章：实际应用场景

4.1 智能客服系统
基于自然语言处理技术，智能客服能够理解用户问题并提供准确回答，大幅提高客户服务效率和满意度。

4.2 内容生成与创作
AI写作助手可以帮助创作者生成文章草稿、营销文案、代码注释等，提高创作效率和质量。

4.3 数据分析与洞察
机器学习算法能够从海量数据中提取有价值的信息和模式，为商业决策提供数据支持。

结语
人工智能技术正在快速发展，深刻改变各行各业。掌握这些核心技术对于适应未来数字化社会至关重要。"""

    with open("documents/ai_comprehensive_guide.txt", "w", encoding="utf-8") as f:
        f.write(sample_content)

    print("✅ 已创建综合示例文档: documents/ai_comprehensive_guide.txt")
    return "documents/ai_comprehensive_guide.txt"


class SimpleEmbeddings:
    """简单的本地嵌入模型，避免网络连接问题"""

    def __init__(self, dimension=384):
        self.dimension = dimension
        # 预定义一些关键词的简单向量表示
        self.keyword_vectors = {
            "机器学习": [0.8, 0.2, 0.1] + [0] * (dimension - 3),
            "深度学习": [0.1, 0.8, 0.2] + [0] * (dimension - 3),
            "神经网络": [0.2, 0.1, 0.8] + [0] * (dimension - 3),
            "人工智能": [0.7, 0.3, 0.2] + [0] * (dimension - 3),
            "监督学习": [0.6, 0.4, 0.1] + [0] * (dimension - 3),
            "无监督学习": [0.4, 0.6, 0.1] + [0] * (dimension - 3),
        }

    def embed_documents(self, texts):
        """为文档生成嵌入向量"""
        vectors = []
        for text in texts:
            # 简单的基于关键词的向量生成
            vector = np.zeros(self.dimension)
            word_count = 0

            for keyword, keyword_vector in self.keyword_vectors.items():
                if keyword in text:
                    vector += np.array(keyword_vector)
                    word_count += 1

            if word_count > 0:
                vector = vector / word_count  # 平均
            else:
                vector = np.random.normal(0, 0.1, self.dimension)  # 随机向量
            vectors.append(vector.tolist())

            return vectors

    def embed_query(self, texts):
        """为文档生成嵌入向量"""
        vectors = []
        for text in texts:
            # 简单的基于关键词的向量生成
            vector = np.zeros(self.dimension)
            word_count = 0

            for keyword, keyword_vector in self.keyword_vectors.items():
                if keyword in text:
                    vector += np.array(keyword_vector)
                    word_count += 1

                if word_count > 0:
                    vector = vector / word_count  # 平均
                else:
                    vector = np.random.normal(0, 0.1, self.dimension)  # 随机向量
                vectors.append(vector.tolist())

    def embed_query(self, text):
        """为查询生成嵌入向量"""
        return self.embed_documents([text])[0]


def document_splitting_demo():
    """文档分割演示"""
    print("\n✂️ 文档分割演示")
    print("-" * 40)

    # 加载文档
    text_path = "documents/ai_comprehensive_guide.txt"
    loader = TextLoader(text_path, encoding="utf-8")
    documents = loader.load()

    original_doc = documents[0]
    print(f"📄 原始文档信息:")
    print(f"   内容长度: {len(original_doc.page_content)} 字符")
    print(
        f"   预估段落数: {original_doc.page_content.count(chr(10)+chr(10)) + 1}"
    )  # chr(10)) 表示换行

    # 演示不同的分割方法

    print("\n1. 按字符分割")
    print("-" * 20)
    char_splitter = CharacterTextSplitter(
        separator="\n\n",
        chunk_size=300,
        chunk_overlap=50,
        length_function=len,
        is_separator_regex=False,
    )

    char_chunks = char_splitter.split_text(original_doc.page_content)
    print(f"   生成块数: {len(char_chunks)}")
    for i, chunk in enumerate(char_chunks[:3]):  # 显示前3个块
        print(f"  块{i+1}: {len(chunk)}字符")
        print(f"  预览：{chunk[:80]}...")

    print("\n2. 递归字符分割（推荐）")
    print("-" * 20)
    recursive_splitter = RecursiveCharacterTextSplitter(
        chunk_size=500,
        chunk_overlap=100,
        length_function=len,
        separators=["\n\n", "\n", "。", "！", "？", "，", " ", ""],
    )

    recursive_chunks = recursive_splitter.split_text(original_doc.page_content)
    print(f"   生成块数: {len(recursive_chunks)}")

    # 显示分割效果
    for i, chunk in enumerate(recursive_chunks[:4]):
        print(f"\n   📍 块 {i+1}:")
        print(f"      长度: {len(chunk)} 字符")
        print(f"      内容: {chunk[:100]}...")
        print(f"      元数据: 来自文档 '{original_doc.metadata['source']}'")

    return {
        "original": original_doc,
        "char_chunks": char_chunks,
        "recursive_chunks": recursive_chunks,
    }


def embedding_vectorization_demo():
    """嵌入向量化演示"""
    print("\n🔢 文本向量化演示")
    print("-" * 40)

    try:
        # 初始化嵌入模型
        print("🔄 加载嵌入模型...")
        embeddings = SimpleEmbeddings(dimension=384)

        # 测试文本
        test_texts = [
            "机器学习是人工智能的核心技术",
            "深度学习使用神经网络",
            "今天天气很好",
        ]

        print("🧪 生成文本向量...")
        vectors = embeddings.embed_documents(test_texts)
        print(f"✅ 成功生成 {len(vectors)} 个文本向量")
        print(f"📊 向量维度: {len(vectors[0])} 维")

        # 显示向量信息
        for i, (text, vector) in enumerate(zip(test_texts, vectors)):
            print(f"\n   文本{i+1}: {text}")
            print(
                f"   向量预览: [{vector[0]:.4f}, {vector[1]:.4f}, ..., {vector[-1]:.4f}]"
            )
            print(f"   向量范数: {sum(x*x for x in vector)**0.5:.4f}")

        return embeddings

    except Exception as e:
        print(f"❌ 向量化失败: {e}")
        return None


def create_vector_store_demo(split_docs, embeddings):
    """创建向量存储演示"""
    print("\n🗄️ 向量数据库创建演示")
    print("-" * 40)

    if not embeddings:
        print("❌ 请先完成嵌入模型初始化")
        return None

    try:
        # 使用分割后的文档创建向量数据库
        texts = split_docs["recursive_chunks"]
        print(f"📝 使用 {len(texts)} 个文本块创建向量数据库...")

        # 创建FAISS向量存储
        vectorstore = FAISS.from_texts(
            texts=texts,
            embedding=embeddings,
            metadatas=[
                {"source": "ai_guide", "chunk_id": i} for i in range(len(texts))
            ],
        )

        print("✅ 向量数据库创建成功!")
        print(f"📊 索引大小: {vectorstore.index.ntotal} 个向量")

        # 演示相似性搜索
        print("\n🔍 相似性搜索演示")
        print("-" * 20)

        test_queries = ["什么是机器学习", "神经网络有哪些类型", "深度学习应用"]
        for query in test_queries:
            print(f"   查询: '{query}'")

            results = vectorstore.similarity_search(
                query, k=2
            )  # 在向量数据库中进行相似性搜索，找到与查询问题最相关的文档片段。query: 搜索的查询文本（"什么是机器学习"）k=2: 返回最相关的 2个 结果
            print(f"   找到 {len(results)} 个相关结果:")
            for i, doc in enumerate(results):
                content_preview = (
                    doc.page_content[:100] + "..."
                    if len(doc.page_content) > 100
                    else doc.page_content
                )
                print(f"     📄 结果 {i+1}: {content_preview}")
            return vectorstore

    except Exception as e:
        print(f"❌ 向量数据库创建失败: {e}")
        return None


def compare_splitting_strategies():
    """比较不同分割策略"""
    print("\n📊 分割策略比较")
    print("-" * 40)

    # 加载文档
    text_path = "documents/ai_comprehensive_guide.txt"
    loader = TextLoader(text_path, encoding="utf-8")
    documents = loader.load()
    original_text = documents[0].page_content

    strategies = [
        ("小尺寸(200)", 200, 40),
        ("中尺寸(400)", 400, 80),
        ("大尺寸(600)", 600, 120),
    ]

    for name, chunk_size, chunk_overlap in strategies:
        splitter = RecursiveCharacterTextSplitter(
            chunk_size=chunk_size, chunk_overlap=chunk_overlap
        )
        chunks = splitter.split_text(original_text)
        print(f"\n🔧 {name}:")
        print(f"   块数: {len(chunks)}")
        avg_length = sum(len(chunk) for chunk in chunks) / len(chunks)
        print(f"   平均长度: {avg_length:.0f} 字符")

    # 显示第一个块作为示例
    if chunks:
        first_chunk_preview = (
            chunks[0][:80] + "..." if len(chunks[0]) > 80 else chunks[0]
        )
        print(f"   示例: {first_chunk_preview}")


def token_based_splitting():
    """基于token的分割演示"""
    print("\n🪙 基于Token的分割")
    print("-" * 40)

    try:
        # 加载文档
        text_path = "documents/ai_comprehensive_guide.txt"
        loader = TextLoader(text_path, encoding="utf-8")
        documetns = loader.load()
        original_text = documetns[0].page_content

        # 使用token分割器
        token_splitter = TokenTextSplitter(
            chunk_size=100, chunk_overlap=20  # 100个token
        )

        token_chunks = token_splitter.split_text(original_text)
        print(f"✅ 生成 {len(token_chunks)} 个token块")

        for i, chunk in enumerate(token_chunks[:2]):
            print(f"\n   Token块 {i+1}:")
            print(f"      长度: {len(chunk)} 字符")
            print(f"      内容: {chunk[:80]}...")

    except ImportError:
        print("❌ Token分割需要tiktoken: pip install tiktoken")
    except Exception as e:
        print(f"❌ Token分割失败: {e}")


# def advanced_splitting_techniques():
#     """高级分割技术演示"""
#     print("\n🎯 高级分割技术")
#     print("-" * 40)

#     # 加载文档
#     text_path = "documents/ai_comprehensive_guide.txt"
#     loader = TextLoader(text_path, encoding="utf-8")
#     documents = loader.load()

#     original_text = documents[0].page_content
#     print("1. 语义感知分割")
#     print("-" * 20)

#     # 基于章节的分割
#     sections = []
#     current_section = []
#     lines = original_text.split("\n")

#     for line in lines:
#         if line.strip() and any(keyword in line for keyword in ["第", "章", "结语"]):
#             if current_section:
#                 sections.append("\n".join(current_section))
#                 current_section = []
#         current_section.append(line)

#     if current_section:
#         sections.append("\n".join(current_section))

#     print(f"   按章节分割: {len(sections)} 个部分")
#     for i, section in enumerate(sections[:3]):
#         lines = section.split("\n")
#         title = lines[0] if lines else "无标题"
#         print(f"     部分 {i+1}: {title[:40]}... ({len(section)} 字符)")

#     print("\n2. 重叠分割策略")
#     print("-" * 20)

#     # 演示不同重叠策略的效果
#     splitter_low_overlap = RecursiveCharacterTextSplitter(
#         chunk_size=400, chunk_overlap=20, length_function=len
#     )

#     splitter_high_overlap = RecursiveCharacterTextSplitter(
#         chunk_size=400, chunk_overlap=100, length_function=len
#     )

#     chunks_low = splitter_low_overlap.split_text(original_text)
#     chunks_high = splitter_high_overlap.split_text(original_text)

#     print(f"   低重叠(20字符): {len(chunks_low)} 个块")
#     print(f"   高重叠(100字符): {len(chunks_high)} 个块")

#     return {
#         "sections": sections,
#         "chunks_low_overlap": chunks_low,
#         "chunks_high_overlap": chunks_high,
#     }


def practical_application_demo(vectorstore):
    """实际应用演示"""
    print("\n🚀 实际应用场景演示")
    print("-" * 40)

    if not vectorstore:
        print("❌ 需要先创建向量数据库")
        return

    # 演示问答场景
    queries = [
        "机器学习有哪些类型？",
        "什么是深度学习？",
        "RAG技术有什么优势？",
        "神经网络的应用场景",
    ]

    print("🤖 智能问答演示:")
    print("-" * 20)

    for query in queries:
        print(f"\n   ❓ 问题: {query}")
        results = vectorstore.similarity_search(query, k=2)

        if results:
            print(f"    📚 找到 {len(results)} 个相关文档:")
            for i, doc in enumerate(results):
                preview = doc.page_content.replace("\n", " ")[:120]
                print(f"      {i+1}.{preview}...")
        else:
            print(f"   ❌ 未找到相关文档")

    # # 演示多轮搜索
    # print("\n🔄 多轮检索演示:")
    # print("-" * 20)

    # follow_up_queries = ["具体说说监督学习", "还有其他的神经网络吗"]

    # for query in follow_up_queries:
    #     print(f"\n   🔍 深入查询: {query}")
    #     results = vectorstore.similarity_search(query, k=1)
    #     if results:
    #         content = results[0].page_content.replace("\n", " ")[:150]
    #         print(f"   💡 找到信息: {content}...")


if __name__ == "__main__":
    print("🎯 Day 5 - 文档分割与向量化学习")
    print("=" * 50)

    # 超创建示例文档
    create_sample_documents()

    # 文档分割演示
    split_results = document_splitting_demo()

    # 向量化演示 - 使用本地模型
    embeddings = embedding_vectorization_demo()

    # 创建向量数据库
    vectorstore = None
    if embeddings and split_results:
        vectorstore = create_vector_store_demo(split_results, embeddings)

    # # 高级分割技术
    # advanced_splitting = advanced_splitting_techniques()

    # 比较不同分割策略
    compare_splitting_strategies()

    # Token分割演示
    token_based_splitting()

    # 实际应用演示
    if vectorstore:
        practical_application_demo(vectorstore)

    print("\n" + "=" * 50)
    print("🎉 Day 5 学习完成！")
    print("\n📚 今日学习总结:")
    print("   ✅ 文档分割技术 - 掌握多种分割策略")
    print("   ✅ 文本向量化 - 理解嵌入模型原理")
    print("   ✅ 向量数据库 - 学会创建和检索向量")
    print("   ✅ 参数调优 - 理解chunk_size和overlap的影响")
    # print("   ✅ 相似性搜索 - 实践语义搜索应用")

    print("\n🔧 核心技术要点:")
    print("   1. RecursiveCharacterTextSplitter - 智能文档分割")
    # print("   2. HuggingFaceEmbeddings - 文本向量化")
    print("   2. CharacterTextSplitter - 简单字符分割")
    print("   3. TokenTextSplitter - Token级别分割")
    print("   4. FAISS - 高效向量相似性搜索")
    # print("   4. chunk_size & chunk_overlap - 关键参数调优")
    print("   5. 自定义嵌入模型 - 解决网络问题")

    print("\n🚀 明日学习预告:")
    print("   📍 RAG系统构建 - 检索增强生成实战")
    print("   📍 对话链设计 - 构建智能问答系统")
    print("   📍 项目实战 - 完整文档问答应用")

    print("\n💡 实践建议:")
    # print("   1. 尝试调整chunk_size观察分割效果")
    # print("   2. 使用自己的文档测试向量化流程")
    # print("   3. 探索不同的嵌入模型和向量数据库")

    print("   1. chunk_size: 200-600字符适用于大多数场景")
    print("   2. chunk_overlap: 10-20%的chunk_size")
    print("   3. 优先使用递归字符分割")
    print("   4. 根据文档类型调整分割策略")

    print("\n🚀 后续改进:")
    print("   当网络畅通时，可以安装: pip install sentence-transformers")
    print("   并使用真实的嵌入模型获得更好的向量化效果")
